﻿#include "ssAsioSession.h"
#include "ssAssert.h"
#include "log/ssLogger.h"
#include "ssAsioNetWork.h"

namespace StarSeeker
{

ssAsioSession::ssAsioSession(void)
{
	m_timeCheck = false;
	m_lastTime = 0;
	m_fastCount = 0;
	m_checkCount = 20;
	m_intervalTime = 100;
	m_sessionID = 0;
	m_pNetMgr = 0;
}

ssAsioSession::~ssAsioSession(void)
{
}

bool ssAsioSession::Init(u32 id, boost::shared_ptr<boost::asio::ip::tcp::socket>& socket, u32 maxBuffSize, ssAsioNetWork* pNetMgr)
{
	m_sessionID = id;
	m_pNetMgr = pNetMgr;
	if (!m_socket)
	{
		m_recvBuf.Init(maxBuffSize);
		m_socket = socket;
		m_socket->set_option(boost::asio::socket_base::receive_buffer_size(maxBuffSize));
		m_socket->set_option(boost::asio::socket_base::send_buffer_size(maxBuffSize));
		m_socket->set_option(boost::asio::socket_base::keep_alive(true));
		m_ip = m_socket->remote_endpoint().address().to_string();
		return true;
	}
	return false;
}

void ssAsioSession::SetTimeCheck(bool timeCheck, i64 intervalTime /*= 100*/, u16 checkCount /*= 20*/)
{
	m_timeCheck = timeCheck;
	m_intervalTime = intervalTime;
	m_checkCount = checkCount;
}

void ssAsioSession::Close(asioClose_e errType, i32 err)
{
	if (m_pNetMgr)
	{
		m_pNetMgr->DoCloseSocket(m_sessionID, errType, err);
	}
}

boost::shared_ptr<boost::asio::ip::tcp::socket>& ssAsioSession::GetSocket()
{
	return m_socket;
}

void ssAsioSession::OnReceive()
{
	if (m_timeCheck)
	{
		i64 now = ssTime::GetTimeNowMS().i64p;
		if (now - m_lastTime < m_intervalTime)//太频繁
		{
			++m_fastCount;
		}
		else
		{
			m_fastCount = 0;
		}
		m_lastTime = now;
		if (m_fastCount > m_checkCount)//超过20次断线
		{
			Close(CLOSE_BY_READ_FAST, 0);
			return;
		}
	}
	if (ParseData())
	{
		m_recvBuf.Empty(false);
	}
}

bool ssAsioSession::ParseData()
{
	if (m_recvBuf.Size() > 0)
	{
		if (m_recvBuf.IsFull())
		{
			SS_LOG->PrintEx("%u recvBuf is full", m_sessionID);
		}

		char* buf = m_recvBuf.Buf();
		ulint len = m_recvBuf.Size();
		ulint readSize = 0;
		u32 runCt = 0;
		while (runCt++ < 400)
		{
			if (len < MSG_HEADER_LEN || len > MSG_MAX_SIZE)
			{
				return true;
			}
			ssNetMsgHead* head = (ssNetMsgHead*)buf;
			//check msg
			if (head->m_dwTcpFlag != MSG_HEADER_FLAG || head->m_dwLen > MSG_MAX_SIZE || head->m_dwLen < MSG_HEADER_LEN)
			{
				return true;
			}
			if (len < head->m_dwLen)
			{
				m_recvBuf.MoveForward(readSize);
				break;
			}
			if (m_pNetMgr)
			{
				//!!需要对象池
				char* tempBuff = new char[head->m_dwLen + 8];
				memcpy(tempBuff, head, head->m_dwLen);
				//抛到上层
				m_pNetMgr->OnSessionMessage(m_ip.c_str(), m_sessionID, head->m_dwMsgID, tempBuff, (ssNetMsgHead*)tempBuff);
			}
			readSize += head->m_dwLen;
			buf += head->m_dwLen;
			len -= head->m_dwLen;
		}
	}
	return false;
}

}
